home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-07-15 | 9.2 KB | 422 lines | [TEXT/MPS ] |
- {$R-}
- UNIT MDEFunit;
-
- INTERFACE
-
- USES Memtypes, Quickdraw, OSIntf, ToolIntf,PackIntf;
-
- procedure MyMenu (message: integer; theMenu: MenuHandle; var MenuRect: rect; hitPt: point; var whichitem: integer);
-
- IMPLEMENTATION
-
- CONST
- normaltext = 0;
- boldtext = 1;
- italictext = 2;
- underlinetext = 4;
- outlinetext = 8;
- shadowtext = 16;
- condensetext = 32;
- extendtext = 64;
-
- mygray = 'AA55AA55AA55AA55';
- FIRST_5_FIELDS = 14;
- FOUR_BYTES = 4;
- INSET_VALUE = 12;
- TEXT_FACE_OFFSET = 3;
- itemheight = 16;
-
-
- PROCEDURE DrawItem(item: Integer; ItemRect: Rect; theMenu: MenuHandle); FORWARD;
-
- PROCEDURE DrawMenu(theMenu: MenuHandle; MenuRect: Rect); FORWARD;
-
- PROCEDURE SizeMenu(theMenu: MenuHandle); FORWARD;
-
-
- function ItemRect (item: integer; MenuRect: Rect): rect; FORWARD;
-
- procedure MyMenu (message: integer; theMenu: MenuHandle; var MenuRect: rect;
- hitPt: point; var whichitem: integer);
- const
- itemheight = 16;
- type
- TwoIntsMakeAlong = RECORD
- CASE INTEGER OF
- 0: (Hi: INTEGER;
- Low: INTEGER);
- 1: (HiAndLow: Longint);
- END;
-
- mbsavelocRec = RECORD
- Mystery: PACKED ARRAY[0..5] OF Byte;
- saveRect: Rect;
- unknownWord: Integer;
- FlagWord: Integer;
- END;
- mbsavelocPtr = ^mbsavelocRec;
- mbsavelocHandle = ^mbsavelocPtr;
- var
- y: integer;
- temp: integer;
- box: rect;
- MenuChoicePtr: ^longint;
- AtMenuBotPtr: ^integer;
- mbsaveholder: ^mbsavelocHandle;
- oldwhichitem: integer;
- mbsavehdl: mbsavelocHandle;
- s: Str255;
- TheChoice: TwoIntsMakeAlong;
- temprect: Rect;
-
- t: MenuHandle;
-
- procedure InvertItem (item: integer; leaveblack: Boolean);
- VAR
- r: Rect;
- rhdl: RgnHandle;
- begin
- rhdl := NewRgn();
- GetClip(rhdl);
- r := ItemRect(item,MenuRect);
- EraseRect(r);
- ClipRect(r);
- DrawItem(item,r,theMenu);
- SetClip(rhdl);
- DisposeRgn(rhdl);
- IF leaveblack THEN
- InvertRect(r);
- end;
-
-
-
- begin
- case message of
- mDrawMsg:
- DrawMenu(theMenu, MenuRect);
-
- mChooseMsg:
- begin
- oldwhichitem := whichitem;
- whichitem := 0;
- MenuChoicePtr := pointer($B54);
-
- if PtInRect(hitPt, MenuRect) then
- begin
-
- y := ((hitpt.v - MenuRect.top) div itemheight) + 1;
-
- {get item rect}
- temprect := itemrect(y,MenuRect);
- mbsaveholder := pointer($B5C);
- mbsavehdl := mbsaveholder^;
-
- {store it in mbSaveLoc}
- temp := themenu^^.menuid;
- TheChoice.hi := themenu^^.menuid;
- TheChoice.low := y;
- MenuChoicePtr^ := TheChoice.HiAndLow;
-
- whichItem := y;
- {}
-
- if whichitem <> oldwhichitem then
-
- begin
- IF ( BTST(theMenu^^.enableFlags,whichitem)) THEN BEGIN
- InvertItem(WhichItem,TRUE);
- InvertItem({y}oldwhichitem,FALSE);
- END
- ELSE BEGIN
- InvertItem(oldwhichitem,FALSE);
- whichItem := 0;
- END;
- end;
- mbsavehdl^^.saveRect := TempRect;
- mbsavehdl^^.FlagWord := 1;
-
- end
- else
- begin
- InvertItem(oldWhichItem,FALSE);
- TheChoice.hi := theMenu^^.menuID;
- TheChoice.low := 0;
- MenuChoicePtr^ := TheChoice.HiAndLow;
- end;
- end;
- mSizeMsg:
- SizeMenu(theMenu);
- otherwise
- sysbeep(10);
- end;
- end;
-
- function ItemRect (item: integer; MenuRect: Rect): rect;
- VAR
- box: Rect;
- begin
- if item > 0 then
- begin
- box := MenuRect;
- box.top := box.top + (item - 1) * itemheight;
- box.bottom := box.top + itemheight;
- end
- else
- SetRect(box, 0, 0, 0, 0);
- ItemRect := box;
- end;
-
-
-
-
-
- PROCEDURE GetStyle(stylenumber: SignedByte; VAR theStyle: Style);
- VAR
- selector: Integer;
- BEGIN
- CASE stylenumber OF
- normaltext:
- theStyle := [];
- boldtext:
- theStyle := [bold];
- italictext:
- theStyle := [italic];
- underlinetext:
- theStyle := [underline];
- outlinetext:
- theStyle := [outline];
- shadowtext:
- theStyle := [shadow];
- condensetext:
- theStyle := [condense];
- extendtext:
- theStyle := [extend];
- otherwise
- theStyle := [];
- END;
- END;
-
-
- PROCEDURE DrawItem(item: Integer; ItemRect: Rect; theMenu: MenuHandle);
-
- VAR
- hierIconRect: Rect;
- shiftIconRect: Rect;
- SICNHdl: Handle;
- fontmetrics: FontInfo;
- graypat: Pattern;
- titlelenght: Integer;
- thestyle: Style;
- gp: GrafPtr;
- I: Integer;
- bm: BitMap;
- titleLength: Integer;
- dataPtr: Ptr;
- tempptr: Ptr;
-
- BEGIN
- {make a gray}
- StuffHex(@graypat,mygray);
- {set the rects for our special icons}
- hierIconRect := ItemRect;
- hierIconRect.left := hierIconRect.right - 16;
-
- shiftIconRect.top := ItemRect.top;
- shiftIconRect.bottom := ItemRect.bottom;
- shiftIconRect.right := hierIconRect.left - 3;
- shiftIconRect.left := shiftIconRect.right - 16;
-
- {now get our 2 SICN's}
- SICNHdl := GetResource('SICN',128); {no checking now we will check whenever we use it}
-
- IF SICNHdl <> NIL THEN BEGIN {we got it make it a bitmap}
- HNoPurge(SICNHdl);
- SetRect(bm.bounds,0,0,16,16);
- bm.rowBytes := 2;
- END;
-
-
- {how long is the title}
- WITH theMenu^^ DO
- titlelength := ORD(menuData[0]) + 1;
-
- {point past it}
- HLock(Handle(theMenu));
-
- {here is where pascal gets to be a pain, C too for that matter}
- WITH theMenu^^ DO
- dataPtr := POINTER(ORD4(@menudata) + titlelength);
-
- FOR I := 1 TO item-1 DO {get to the item's data}
- dataPtr := POINTER(ORD4(dataPtr) + dataPtr^ + FOUR_BYTES + 1);
-
- {now we are pointing at the data for the item we care about}
- IF StringPtr(dataptr)^ = '-' THEN BEGIN
- PenPat(graypat);
- MoveTo(ItemRect.left,ItemRect.top + 8);
- LineTo(ItemRect.right,ItemRect.top + 8);
- PenNormal;
- END
- ELSE BEGIN
- {what is the typeface}
- tempptr := POINTER(ORD4(dataptr) + dataPtr^ + 1 + TEXT_FACE_OFFSET);
- GetStyle(tempptr^,thestyle);
- TextFace(thestyle);
- GetFontInfo(FontMetrics);
- MoveTo(ItemRect.left + INSET_VALUE,ItemRect.bottom - FontMetrics.descent);
- DrawString(StringPtr(dataPtr)^);
- TextFace([]);
-
- {look at the icon bit, we don't support real icons (its too hard to figure item height)}
- {anyway they look stupid in menus}
- tempptr := POINTER(ORD4(dataptr) + dataPtr^ + 1);
- IF tempptr^ = 1 THEN {it is a shift command item so draw the shift icon}
- IF SICNHdl <> NIL THEN BEGIN
-
- GetPort(gp);
- HLock(SICNHdl);
- bm.baseAddr := SICNHdl^;
- CopyBits(bm,gp^.portBits,bm.bounds,shiftIconRect,srcCopy,nil);
- HUnlock(SICNHdl);
- END;
-
- {check command key}
- tempptr := POINTER(ORD4(tempptr) + 1);
- IF tempptr^ > $1F THEN BEGIN {draw the character}
- MoveTo(ItemRect.right - 24,ItemRect.bottom - FontMetrics.descent);
- DrawChar(CHR(17));
- DrawChar(CharsPtr(tempptr)^[0]);
- END
- ELSE
- IF tempptr^ = $1B THEN {we have a submenu so draw the indicator}
- IF SICNHdl <> NIL THEN BEGIN
-
- GetPort(gp);
- HLock(SICNHdl);
- bm.baseAddr := POINTER(ORD4(SICNHdl^) + 32);
- CopyBits(bm,gp^.portBits,bm.bounds,hierIconRect,srcCopy,nil);
- HUnlock(SICNHdl);
- END;
-
- {finally if it is disabled }
- IF (NOT BTST(theMenu^^.enableFlags,item)) THEN BEGIN
- PenPat(graypat);
- PenMode(patBic);
- ItemRect.right := ItemRect.right - 2;
- ItemRect.left := ItemRect.left + 4;
- PaintRect(ItemRect);
- PenNormal;
- END;
-
- IF SICNHdl <> NIL THEN
- HPurge(SICNHdl);
- HUnlock(Handle(theMenu));
- END; {of drawing code}
- END;
-
- PROCEDURE SizeMenu(theMenu: MenuHandle);
- CONST
- ITEMHEIGHT = 16;
- HierIconWidth = 16;
- Slop = 18;
- shiftIconWidth = 19;
- TYPE
- FourBytes = PACKED ARRAY[0..3] OF SignedByte;
- FourBytePtr = ^FourBytes;
- VAR
- maxWidth: Integer;
- dataPtr: Ptr;
- numItems: Integer;
- tempwidth: Integer;
- AddSlop: Boolean;
- I: Integer;
-
- BEGIN
-
- {we use stringwidth so lock the menuhandle}
- HLock(Handle(theMenu));
-
- WITH theMenu^^ DO
- dataPtr := @menudata;
-
- {move past the title}
- dataPtr := POINTER(ORD4(dataPtr)+dataPtr^+1);
-
- numItems := CountMItems(theMenu);
- theMenu^^.menuHeight := numItems * ItemHeight; {gross, but simple}
-
- {now figure out the width}
- maxWidth := INSET_VALUE;
- AddSlop := FALSE;
- FOR I := 1 TO numItems DO BEGIN
-
- IF dataPtr^ <> ORD('-') THEN BEGIN {the lines are as long as the longest item}
- TextFont(0);
- tempwidth := StringWidth(StringPtr(dataPtr)^) + 4;
-
- {increment dataPtr to point at do-dads}
- dataPtr := POINTER(ORD4(dataPtr)+dataPtr^+1); {first at icon byte}
-
- IF FourBytePtr(dataPtr)^[0] = 1 THEN BEGIN {uses shift icon}
- tempwidth := tempwidth + shiftIconWidth ;
- AddSlop := TRUE;
- END;
-
- {dataPtr := POINTER(ORD4(dataPtr)+1);} {now at command byte}
- IF FourBytePtr(dataPtr)^[1] > $1F THEN BEGIN
- tempwidth := tempwidth + CharWidth(CHR(17)) + CharWidth(CharsPtr(dataPtr)^[1]);
- { CharWidth(CHR(dataPtr^));}
- AddSlop := TRUE;
- END
- ELSE
- IF FourBytePtr(dataPtr)^[1] = $1B THEN BEGIN
- tempwidth := tempwidth + HierIconWidth;
- AddSlop := TRUE;
- END;
-
- {don't feel like supporting Marks either. I'll leave it as an exercise}
-
- IF AddSlop THEN
- tempwidth := tempwidth + Slop;
-
- IF tempwidth > maxWidth THEN
- maxWidth := tempwidth;
-
- {add four to data ptr so we point at start of next string}
- dataPtr := POINTER(ORD4(dataPtr)+4);
- END;
-
- theMenu^^.menuWidth := maxWidth;
- END;
- HUnlock(Handle(theMenu));
- END;
-
-
-
-
-
-
-
-
-
-
- PROCEDURE DrawMenu(theMenu: MenuHandle; MenuRect: Rect);
- VAR
- numItems: Integer;
- I : Integer;
- theRect: Rect;
-
- BEGIN
-
- numItems := CountMItems(theMenu);
-
- FOR I := 1 TO numItems DO BEGIN
- theRect := ItemRect(I,MenuRect);
- DrawItem(I,theRect,theMenu);
- END;
-
- END;
-
- END.
-
-